﻿using System;
using System.Linq;
using System.Web.Mvc;
using LCA.Community.DAL.Interfaces;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using System.Configuration;

namespace LCA.Community.Web.Filters
{
    public enum SecurityRequisitesOptions
    {
        Admin,
        Owner,
        Friend,
        GroupMember,
        GroupOwner,
        Registered
    }

    [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class SecurityFilter : ActionFilterAttribute
    {
        public IUnityContainer _container;
        public string SecurityRequisites{get;set;}
        public string SolvingActionParameter { get; set; }
        public string ErrorResource{get;set;}

        public SecurityFilter()
        {
            _container = MvcApplication.Container;
        }

        public override void  OnActionExecuting(ActionExecutingContext filterContext)
        {
            if ((SecurityRequisites.Split(new[] {','}).Select(
                    o => (SecurityRequisitesOptions) Enum.Parse(typeof (SecurityRequisitesOptions), o))).Any(
                    x => IsValidRole(x, filterContext))) 
                return;
            filterContext.HttpContext.Response.Redirect(new UrlHelper(filterContext.RequestContext).Action("Index", "Error", new { errorResource = ErrorResource }), true);
        }

        private bool IsValidRole(SecurityRequisitesOptions option, ActionExecutingContext filterContext)
        {
            bool result = true;
            string id;

            try
            {
                id = (string)filterContext.HttpContext.Session["ID"];
            }
            catch
            {
                id = null;
            }
            string idParameter;
            try
            {
                idParameter = (string)filterContext.ActionParameters[SolvingActionParameter];
            }
            catch
            {
                idParameter = null;
            }
            try
            {
                var usersRepository = _container.Resolve<IUsersRepository>();
                var groupsRepository = _container.Resolve<IGroupsRepository>();

                switch (option)
                {
                    case SecurityRequisitesOptions.Registered:
                        if (id == null)
                        {
                            result = false;
                        }
                        break;
                    case SecurityRequisitesOptions.Friend:
                        var friendsRepository = _container.Resolve<IFriendshipsRepository>();

                        if ((id == null) || (idParameter == null) ||
                           (usersRepository.Get(idParameter) == null) || 
                            (!friendsRepository.AreFriends(id,idParameter)))
                        {
                            result = false;
                        }
                        break;
                    case SecurityRequisitesOptions.GroupMember:
                        var groupMembershipsRepository = _container.Resolve<IGroupMembershipsRepository>();

                        if ((id == null) || (idParameter == null) ||
                            (groupsRepository.Get(idParameter) == null) ||
                           (groupMembershipsRepository.Get(idParameter,id) == null))
                        {
                            result = false;
                        }
                        break;
                    case SecurityRequisitesOptions.GroupOwner:

                        if ((id != null) && (idParameter != null))
                        {
                            var group = groupsRepository.Get(idParameter);

                            if ((group == null) || (!group.Owner.Equals(id)))
                                result = false;
                        }
                        else
                        {
                            result = false;
                        }
                        break;
                    case SecurityRequisitesOptions.Owner:

                        if (id == null || idParameter == null || idParameter != id)
                        {
                            result = false;
                        }
                        break;
                    case SecurityRequisitesOptions.Admin:
                        var adminsRepository = _container.Resolve<IAdminsRepository>();
                        if ((id == null) ||
                            (!adminsRepository.IsAdmin(id)))
                        {
                            return false;
                        }
                        break;
                }
            }
            catch (NullReferenceException)
            {
                result = false;
            }
            return result;
        }
    }
}
